package Socket;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import static java.lang.Thread.sleep;

/*
SockUtil中发送和读取都是string
！！！！
SockUtil中接收完后会关闭接收通道
接收完后重新打开

暂定：设定一个特殊字符，等读取到该字符后停止读取
问题：1.如果设\n为末尾字符，在传输测试和选择时无法正确判断
     2.后期ui做好后冲文本框读入没有\n
     3

已解决
 */

/*
等大方向写完后改

目前单对单非重大影响问题：
    1.对方下线后，无法重新选择
    2.客户端下线后对应的数组下标无法使用
    3.如果在某个客户端下线后，有新的客户端重新连接，无法将无法连接的客户端进行提示
    4.无法在聊天中重新选择。
 */

/*
聊天室大概思路：



 */



/*
新想法：
    ai聊天
    调用api，用户可以选择和ai对话
    暂定

 */


/*
新想法：
    服务器可开3个大线程
    一个用于选择

    一个用于单对单
    一个用于聊天室

    ai聊天可以在客户端调用api实现

    客户端ui大概实现
    登录
    选择功能（先不支持实时修改功能）：
        1.单对单-》进入单对单线程 （保留目前实现的ui）
        2.聊天室-》聊天室线程
        3.ai对话-》客户端调用api


    服务器大概流程
    单对单
        维护一个单对单客户端数组

      看选择线程维护的标志数组，如果为1，将其添加进端对端数组里（替换原来的accept连接添加）

    聊天室
        维护一个聊天室数组
       同上，如果为2，添加到聊天室数组里。
       （实现大概和单对单差不多）

       大概实现思路，
       和单对单一样，每添加一个客户端就开一个线程单独为其服务
       该线程查看客户端是否发出信息和转发给所有聊天室客户端

       接收消息
       发送所有

    1.选择线程
        搞一个标志数组初始化为0，如果有新客户端连接

 */

public class Ser{
    //public ServerSocket(int port) throws IOException;
    private ServerSocket server;

    //最多连接100个客户端
    private static Socket[] connect = new Socket[100];

    //标记当前客户端连接的数量-1;
    //初始值为-1，每次循环开头++为接下来要连接的客户端的序号
    private static int flag = -1;

    public Ser() throws IOException {
        this.server = new ServerSocket(23333);
    }

    public void startSer(){
        while(true){
            try{
                flag++;
                connect[flag] = server.accept();

                /*
                创建一个线程，然后该线程和连接的客户端通信
                 */
                Thread t = new Thread(new SerTask(flag));
                t.start();

                System.out.println("客户端"+flag+"已连接！！");

            }catch (IOException e){
                e.printStackTrace();
            }
        }

    }

    /*
    服务器线程要执行的任务
    一个线程对应一个客户端
     */
    static class SerTask implements Runnable{
        //记录当前客户端在Ser.conncet[]中的序号
        private int local;

        //客户端选择的聊天对象
        private int choice;

        //通过构造函数将连接到的客户端传进来
        public SerTask(int flag){
            this.local = flag;
        }

        @Override
        public void run(){
            try {
                System.out.println("进入线程"+local);
                System.out.println("现在是客户端"+local+"工作");
                /*
                一直向客户端发送flag;
                客户端循环等待，当flag>=1时，
                发送消息让服务器停止发送flag;
                客户端发0则继续发，客户端发1则停止
                停止后，服务器接收客户端发来的chocie;
                让用户来选择小于flag的数作为聊天对象
                 */
                String test = SockUtil.receiveMsg(connect[local]);
                System.out.println(test);

                //发送local
                SockUtil.sendMsg(connect[local],String.valueOf(local));

                if(test.equals("success!")){
                    while(true){
                        sleep(100);
                        int b = 0;
                        String sflag = String.valueOf(flag);
                        System.out.println(flag+"和"+sflag);
                        SockUtil.sendMsg(connect[local],sflag);
                        System.out.println("向"+local+"发送了一次flag");
                        b = Integer.parseInt(SockUtil.receiveMsg(connect[local]));
                        if(b == 1) break;
                    }
                    choice = Integer.parseInt(SockUtil.receiveMsg(connect[local]));

                /*
                现在开始接收信息
                接收客户端的信息，然后发给对应的connect[choice];
                 */
                    String recv;
                    String send;
                    while(true){
                        recv = SockUtil.receiveMsg(connect[local]);
                        send = "客户端"+local+":"+recv;
                        SockUtil.sendMsg(connect[choice],send);
                    }
                }
            } catch (IOException e) {
                //当一方关闭后，向双方发送消息提示下线
                String tip = "对端已下线";
                System.out.println(tip);
                try {
                    SockUtil.sendMsg(connect[choice],tip);
                    SockUtil.sendMsg(connect[local],tip);
                } catch (IOException ex) {

                }

                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                //sleep
                throw new RuntimeException(e);
            }
        }
    }

}
